package store

import (
	"codejy/structdef"
	"codejy/utils"
	"fmt"
	"strings"
)

// 默认 全局环境,类型环境,当前操作环境,操作文件路径 ,用于命令行中执行代码
var CmdDefaultEnv = "@context@"

// 其他工作目录,其他工作目录导包时候需要使用@符号作为前缀,如@test\xxx 就会去其他工作目录下查找
var CurrentOtherDir []string

// 主文件所在的主目录
var MainFileDir string

// 当前执行代码所在的主目录
var CurrentExeDir string

// 核心文件是否加载
var CoreFileLoaded = false

var MainThreadStore *structdef.ThreadStore

// 主文件路径,代码入口
var MainFilePath string

type Void struct{}

// 已经加载的文件, 如果是false,那么就表示定义加载完成了,如果是true,那么就表示文件所有代码执行完成了
var LoadedFile = make(map[string]bool)

// 关键字集
var keywords = map[string]Void{
	"break":    Void{},
	"import":   Void{},
	"if":       Void{},
	"switch":   Void{},
	"for":      Void{},
	"global":   Void{},
	"type":     Void{},
	"share":    Void{},
	"this":     Void{},
	"core&":    Void{},
	"threadId": Void{},
	"to":       Void{},
	"var":      Void{},
}

// 检测是否是关键字
func IsKeyword(word string) bool {
	_, ok := keywords[word]
	if ok {
		return false
	}
	return true
}

// 所在文件.jy -> 导入文件名,文件全路径
var ImportFile = make(map[string]map[string]string)

// 添加导入文件
// 意思就是fileNamePath里面导入了importFileName文件,importFileName文件的全路径是importFilePath
func AddImportFile(fileNamePath string, importFileName string, importFilePath string) {
	_, ok := ImportFile[fileNamePath]
	if !ok {
		ImportFile[fileNamePath] = make(map[string]string)
	}
	//判断是否已经存在
	_, ok = ImportFile[fileNamePath][importFileName]
	if ok {
		panic("当前文件导入文件中存在重复文件名的情况[" + importFilePath + "]请使用as别名的方式导入")
	}

	ImportFile[fileNamePath][importFileName] = importFilePath
}

// 查询导入文件,文件名称对应的的全路径
func GetImportFile(fileNamePath string, importFileName string) string {
	//如果是命令行执行,那么就通过importFileName.jy找后缀匹配的文件
	if CmdDefaultEnv == fileNamePath {
		importFileName = importFileName + ".jy"
		for s := range ImportFile {
			if strings.HasSuffix(s, importFileName) {
				importFileName = s
				break
			}
		}
		return importFileName
	}
	_, ok := ImportFile[fileNamePath]
	if !ok {
		return ""
	}
	path, ok := ImportFile[fileNamePath][importFileName]
	if !ok {
		return ""
	}
	return path
}

// 实例恢复执行器
func NweStatusRestore(threadStore *structdef.ThreadStore, execute func() string) string {
	InstanceAddress1 := threadStore.CurrentInstanceAddress //保存当前实例地址
	threadStore.ParentInstanceAddress = InstanceAddress1   //设置父级实例地址
	utils.DebugLog("当前操作的父实例地址", func() {
		fmt.Println(InstanceAddress1)
	})
	defer func() {
		//恢复实例地址
		threadStore.CurrentInstanceAddress = InstanceAddress1
		threadStore.ParentInstanceAddress = ""
	}()
	return execute()
}

// 执行完毕函数后状态还原为父作用域
func FuncStatusRestore(threadStore *structdef.ThreadStore, execute func(parentEnv string, parentCodes []structdef.LineCodeDefinition, parentCode structdef.LineCodeDefinition)) {
	//(父作用域)信息
	parentEnv := threadStore.CurrentEnv
	parentCodes := threadStore.Codes
	parentCode := threadStore.Code
	parentPoin := threadStore.CurrentPoint
	parentParentEnv := threadStore.ParentEnv
	defer func() {
		//恢复用域
		AddCurrentEnv(threadStore, parentEnv)
		AddParentEnv(threadStore, parentParentEnv)
		//恢复代码
		threadStore.Codes = parentCodes
		threadStore.Code = parentCode
		//恢复指针
		threadStore.CurrentPoint = parentPoin
	}()
	execute(parentEnv, parentCodes, parentCode)
}

// 切换到指定文件执行,执行完毕后恢复到原来的文件
func RealityFilePathSwitch(threadStore *structdef.ThreadStore, fileName string, execute func() string) string {
	//保存当前操作的文件名
	handleFilePath := threadStore.HandleFilePath
	file := GetImportFile(handleFilePath, fileName)
	threadStore.HandleFilePath = file
	defer func() {
		//还原当前操作的文件名
		threadStore.HandleFilePath = handleFilePath
	}()
	return execute()
}

// 获取CoreFileLoaded
func GetCoreFileLoaded() bool {
	return CoreFileLoaded
}

// 设置
func SetCoreFileLoaded(is bool) {
	CoreFileLoaded = is
}
